package org.nkywz.android.magiccube;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

public class Cube {

	private static final int COLOR = 0x5000;
	private static final int ALPHA = 0x5000;
	private static final int UNIT = 0x5000;
	
	private static int[] center = {
		-UNIT, -UNIT, -UNIT,
		UNIT, -UNIT, -UNIT,
		UNIT, UNIT, -UNIT,
		-UNIT, UNIT, -UNIT,
		-UNIT, -UNIT, UNIT,
		UNIT, -UNIT, UNIT,
		UNIT, UNIT, UNIT,
		-UNIT, UNIT, UNIT
	};
	
	private ArrayList<IntBuffer> mVertexBuffer;
    private ArrayList<IntBuffer> mColorBuffer;

	private int x, y, z;

	public Cube(int x, int y, int z) {
		this.x = x;
		this.y = y;
		this.z = z;
		
		mVertexBuffer = new ArrayList<IntBuffer>();
		mColorBuffer = new ArrayList<IntBuffer>();
		
		int[] tmpVertices;
		int[] tmpColors = new int[16];
		ByteBuffer vbb, cbb;
		IntBuffer tmpBuffer;
		
		switch(x) {
		case -1:	// left - Red
			tmpVertices = generateVertices(0, 3, 4, 7);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = COLOR;
				tmpColors[i * 4 + 1] = 0;
				tmpColors[i * 4 + 2] = 0;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		case 1:		// right - Green
			tmpVertices = generateVertices(6, 2, 5, 1);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = 0;
				tmpColors[i * 4 + 1] = COLOR;
				tmpColors[i * 4 + 2] = 0;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		default:
		}

		switch(y) {
		case -1:	// bottom - Blue
			tmpVertices = generateVertices(1, 0, 5, 4);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = 0;
				tmpColors[i * 4 + 1] = 0;
				tmpColors[i * 4 + 2] = COLOR;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		case 1:		// top - R+G
			tmpVertices = generateVertices(2, 6, 3, 7);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = COLOR;
				tmpColors[i * 4 + 1] = COLOR;
				tmpColors[i * 4 + 2] = 0;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		default:
		}

		switch(z) {
		case -1:	// back - R+B
			tmpVertices = generateVertices(0, 1, 3, 2);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = COLOR;
				tmpColors[i * 4 + 1] = 0;
				tmpColors[i * 4 + 2] = COLOR;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		case 1:		// front - G+B
			tmpVertices = generateVertices(6, 5, 7, 4);
			vbb = ByteBuffer.allocateDirect(tmpVertices.length * 4);
			vbb.order(ByteOrder.nativeOrder());
			tmpBuffer = vbb.asIntBuffer();
			tmpBuffer.put(tmpVertices);
			tmpBuffer.position(0);
			mVertexBuffer.add(tmpBuffer);
			
			for (int i = 0; i < 4; i++) {
				tmpColors[i * 4] = 0;
				tmpColors[i * 4 + 1] = COLOR;
				tmpColors[i * 4 + 2] = COLOR;
				tmpColors[i * 4 + 3] = ALPHA;
			}
			cbb = ByteBuffer.allocateDirect(tmpColors.length * 4);
			cbb.order(ByteOrder.nativeOrder());
			tmpBuffer = cbb.asIntBuffer();
			tmpBuffer.put(tmpColors);
			tmpBuffer.position(0);
			mColorBuffer.add(tmpBuffer);
			break;
		default:
		}
	}
	
	private int[] generateVertices(int v1, int v2, int v3, int v4) {
		int[] vert = new int[12];
		vert[0] = center[v1 * 3] + 2 * UNIT * x;
		vert[1] = center[v1 * 3 + 1] + 2 * UNIT * y;
		vert[2] = center[v1 * 3 + 2] + 2 * UNIT * z;
		vert[3] = center[v2 * 3] + 2 * UNIT * x;
		vert[4] = center[v2 * 3 + 1] + 2 * UNIT * y;
		vert[5] = center[v2 * 3 + 2] + 2 * UNIT * z;
		vert[6] = center[v3 * 3] + 2 * UNIT * x;
		vert[7] = center[v3 * 3 + 1] + 2 * UNIT * y;
		vert[8] = center[v3 * 3 + 2] + 2 * UNIT * z;
		vert[9] = center[v4 * 3] + 2 * UNIT * x;
		vert[10] = center[v4 * 3 + 1] + 2 * UNIT * y;
		vert[11] = center[v4 * 3 + 2] + 2 * UNIT * z;
		return vert;
	}

	public void draw(GL10 gl) {
		int i = 0;
		for (IntBuffer buffer : mVertexBuffer) {
			gl.glVertexPointer(3, GL10.GL_FIXED, 0, buffer);
			gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer.get(i++));
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
		}
	}
}
